#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int get_sp_count(const char *str);
int validate_sign(char *source,char *gaczKey);
int GetField(char *epczBuf,char *opczStr, char cDelim, int eiFiledNum);
void proc_info(char *eopBuf);
char * kill_lf( char *pczStr );
int to_xml(char *source);

extern char * __MD5(int in_iLen, const char *in_pszIn, int in_iFlag);

int my_sort(const void *epczBuf1, const void * epczBuf2)
{
	return strcmp((char*)epczBuf1, (char *)epczBuf2);
}

int main()
{
	char str[] = "busiId=123456789&time=1619144524656&version=1&sign=2705bb76b2554bd38befeecd996f81f9";
	char str1[] = "topnet";
	int re = url_alidate_and_to_xml(str,str1);
	printf("%d\n",re);
	return 0;
}

int url_alidate_and_to_xml(char *source,char *key)
{
	int iRet = -1; 
	do
	{
		iRet = validate_sign(source,key);
		if(iRet == -1)
		{
			break;
		}
		iRet = to_xml(source);		
	}while(0);
	return iRet;
}

int validate_sign(char *source,char *gaczKey)
{
	int num = get_sp_count(source);
	int i;
	char aczData[10][4096*10];
	char aczHeadBuf[1024];
	char aczKey[100+1];
	char aczMd5[32+1];
	char aczRecvBuf[4096*10];
	char aczLocalMd5[32+1];
	char aczSignData[4096*10];
	
	memset(aczData,0x00,sizeof(aczData));
	memset(aczHeadBuf,0x00,sizeof(aczHeadBuf));
	memset(aczKey,0x00,sizeof(aczKey));
	
	for(i = 0; i < num; i++)
	{
		GetField(source, aczData[i], '&', i+1);
		kill_lf(aczData[i]);
		proc_info(aczData[i]);
		printf("%s\n",aczData[i]);	
	}
	qsort(aczData,num, sizeof(aczData[0]), my_sort);
	for(i=0;i<num;i++)
	{
		if(!strncmp(aczData[i], "sign=", 5))
		{
			memset(aczMd5, 0x00, sizeof(aczMd5));
			GetField(aczData[i], aczMd5, '=', 2);
			continue;
		}

		if(!strncmp(aczData[i], "data=", 5))
		{
			memset(aczRecvBuf, 0x00, sizeof(aczRecvBuf));
			snprintf(aczRecvBuf, sizeof(aczRecvBuf), "%s", aczData[i]+5);
			continue;
		}
		strcat(aczHeadBuf, aczData[i]);
		strcat(aczHeadBuf, "&");
	}	
	memset(aczSignData, 0x00, sizeof(aczSignData));
	snprintf(aczSignData, sizeof(aczSignData), "%s%s", aczHeadBuf, gaczKey);
	printf("sing_data=[%s]",aczSignData);
	snprintf(aczLocalMd5, sizeof(aczLocalMd5), "%s", __MD5(strlen(aczSignData), aczSignData, 2));
	printf("local md5=[%s] remote md5=[%s]\n",aczLocalMd5,aczMd5);
	if(strcmp(aczMd5, aczLocalMd5))
	{
		printf("sign data error[%s][%s]\n",aczLocalMd5,aczMd5);		
		return -1;
	}
	return 0;
}

int to_xml(char *source)
{
	int iRet;
	int i;
	int num = get_sp_count(source);
	char tmp[4096*10];
	char name[100];
	char xml_data[1024*1024];
	memset(xml_data,0x00,sizeof(xml_data));
	iRet = sprintf(xml_data,"%s","<?xml version=\"1.0\" encoding=\"UTF-8\"?><url_to_xml>");
	for(i = 0; i < num; i++)
        {
		memset(tmp,0x00,sizeof(tmp));
		memset(name,0x00,sizeof(name));
                GetField(source, tmp, '&', i+1);
		GetField(tmp,name, '=',1);	
		iRet += snprintf(xml_data+iRet,sizeof(xml_data)-iRet,"<%s>%s</%s>",name,tmp+strlen(name)+1,name);
		
        }
	strcat(xml_data,"</url_to_xml>");	
	printf("%s\n",xml_data);
	printf("iRet = %d\n",iRet);
	return iRet;
}
/* 计算分割之后的数据数目 */
int get_sp_count(const char *str)
{
	int iRet = 0;
	while(*str++ != '\0')
	{
		if(*str == 0x26)
		{
			iRet++;
		}
	}
	//比分隔符多一个 
	return iRet+1;
}

int GetField(char *epczBuf,char *opczStr, char cDelim, int eiFiledNum)
{
    int iNum=1;
    int iCout=0;
    int iFlag = 0;
    unsigned char ucTemp = 0;
    if ( !epczBuf || eiFiledNum <=0 )
        return -1;
    while ( *epczBuf != 0x00 )
    {
        ucTemp = (unsigned char)*epczBuf;

        if ( *epczBuf != cDelim || (*epczBuf == cDelim && iFlag))
        {
            if ( iNum == eiFiledNum )
            {
                opczStr[iCout] = *epczBuf;
                iCout++;
            }
        }
        else
        {
            iNum++;
            if ( iNum > eiFiledNum )
                break;
        }
        if(!iFlag && ucTemp > 127)
        {
            iFlag = 1;
        }
        else
        {
            iFlag = 0;
        }
        epczBuf++;
    }
    opczStr[iCout] = 0x00 ;
    if ( iNum < eiFiledNum )
        return -1;
    return iCout ;
}


void proc_info(char *eopBuf)
{
    char aczBuf[4096*10];
    char aczTemp[100];
    int j = 0;
    char *p = eopBuf;
    memset(aczBuf, 0x00, sizeof(aczBuf));

    if(!strstr(eopBuf, "%"))
    {
        return;
    }

    for(; *eopBuf; )
    {
        if(*eopBuf == '%')
        {
            memset(aczTemp, 0x00, sizeof(aczTemp));
            strncpy(aczTemp, eopBuf+1, 2);
            aczBuf[j++]= (char)strtol(aczTemp, NULL, 16);
            eopBuf+=3;
        }
        else
        {
            aczBuf[j++]=*eopBuf++;
        }
    }

    strcpy(p, aczBuf);
}

char * kill_lf( char *pczStr )
{
    char *pczTmp ;
    pczTmp=pczStr;
    while( *pczTmp == 0x20 ) pczTmp++;
    pczStr = pczTmp;
    if(pczStr[0])
    {
        pczTmp=pczStr+strlen(pczStr) - 1;
        while ( *pczTmp==0x20 || *pczTmp==0x0d || *pczTmp==0x0a ) pczTmp--;
        *(pczTmp+1)=0x00;
    }
    return pczStr;
}
